﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Nomo.UnityCoreModule
{
    public sealed class PredicationScheduler : MonoBehaviour
    {
        public class PredicationSchedulerTask
        {
            public readonly Func<bool>[] Predicates;
            public readonly Action       Completed;

            public PredicationSchedulerTask(IEnumerable<Func<bool>> predicates, Action completed)
            {
                Predicates = predicates.ToArray();
                Completed  = completed;
            }
        }

        private readonly Dictionary<Guid, PredicationSchedulerTask>          _dictionary = new Dictionary<Guid, PredicationSchedulerTask>();
        private readonly Queue<KeyValuePair<Guid, PredicationSchedulerTask>> _queue      = new Queue<KeyValuePair<Guid, PredicationSchedulerTask>>();

        public void Add(PredicationSchedulerTask predicationSchedulerTask, out Guid guid)
        {
            guid = Guid.NewGuid();
            _dictionary.Add(guid, predicationSchedulerTask);
        }

        public void Remove(Guid guid)
        {
            _dictionary.Remove(guid);
        }

        private void Update()
        {
            _queue.Clear();
            foreach (var keyValuePair in _dictionary)
            {
                _queue.Enqueue(keyValuePair);
            }
            while (_queue.Count != 0)
            {
                var keyValuePair = _queue.Dequeue();
                try
                {
                    if (keyValuePair.Value.Predicates.Any(e => e()))
                    {
                        keyValuePair.Value.Completed?.Invoke();
                        _dictionary.Remove(keyValuePair.Key);
                    }
                }
                catch
                {
                    _dictionary.Remove(keyValuePair.Key);
                }
            }
        }
    }
}
